package com.jt.www.biz.pay.service.impl;

import com.jt.www.biz.pay.service.PayOutService;
import com.jt.www.biz.pay.service.PolicyGetService;
import com.jt.www.dao.mapper.issue.mapper.IssuePolicyLogEntityMapper;
import com.jt.www.dao.mapper.issue.mapper.IssueRecordEntityMapper;
import com.jt.www.dao.mapper.woxuebao.PayUrlInfoMapper;
import com.jt.www.enums.issue.IssueEnum;
import com.jt.www.enums.woxuebao.PayOutStatusEnum;
import com.jt.www.model.issue.entity.IssuePolicyLogEntity;
import com.jt.www.model.issue.entity.IssueRecordEntity;
import com.jt.www.model.woxuebao.PayUrlInfoEntity;
import com.jt.www.remote.DexClient;
import com.jt.www.util.DateUtils;
import com.jt.www.util.JsonUtil;
import com.jt.www.util.RedisUtil;
import org.apache.commons.collections.CollectionUtils;
import org.dom4j.Document;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.weekend.Weekend;
import tk.mybatis.mapper.weekend.WeekendCriteria;

import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 * 调用太保查询保单号接口任务
 * Created by shaoyn on 2020/08/21.
 */
@Service
public class PolicyGetServiceImpl implements PolicyGetService {

    public static final Logger log = LoggerFactory.getLogger(PolicyGetServiceImpl.class);

    //锁前缀
    private static final String MESSAGE_LOCK_KEY = "EDU_TPY_JF_ISSUE";
    //锁超时时间
    private static final Long MESSAGE_TIME_OUT = 2L;

    @Autowired
    private PayUrlInfoMapper payUrlInfoMapper;

    @Autowired
    private IssueRecordEntityMapper issueRecordEntityMapper;

    @Autowired
    private IssuePolicyLogEntityMapper issuePolicyLogEntityMapper;

    @Autowired
    private DexClient dexClient;
    @Autowired
    private PayOutService payOutService;

    @Override
    public void tpyIssueEffect(Integer times) {
        //如果一个定时任务在执行，那么下一个定时不能执行
        if (!RedisUtil.setLock(MESSAGE_LOCK_KEY, "1", MESSAGE_TIME_OUT)) {
            //  log.info("调用太保承保接口任务==>当天任务已经执行，不在重复执行");
            return;
        }
        String findCode = "tpyIssueEffect_" + System.currentTimeMillis();
        try {
            log.info("{}太保-见费出单，调用太保查询保单号接口任务 开始执行", findCode);
            Weekend<PayUrlInfoEntity> weekend = Weekend.of(PayUrlInfoEntity.class);
            WeekendCriteria<PayUrlInfoEntity, Object> criteria = weekend.weekendCriteria();
            criteria.andEqualTo(PayUrlInfoEntity::getPayUrlStatus, true);
            criteria.andEqualTo(PayUrlInfoEntity::getPayStatus, false);
            criteria.andLessThan(PayUrlInfoEntity::getIssueTimes, times);
            //暂时只查 临沂的，如果以后还有其他的用in
            criteria.andEqualTo(PayUrlInfoEntity::getProCode, IssueEnum.CODE_40.getProCode());

            List<PayUrlInfoEntity> list = payUrlInfoMapper.selectByExample(weekend);
            log.info("{}调用太保查询保单号接口任务 记录数{}", findCode, list.size());
            if (CollectionUtils.isNotEmpty(list)) {
                list.forEach(payUrlInfo -> {
                    String seqNo = Long.toString(Math.abs(new Random().nextLong()));
                    String detailFindCode = findCode + "_" + seqNo;
                    log.info("{}调用太保查询保单号接口任务 applicationFormCode:{},applyPolicyNo:{},cpcNoticeNo:{}",
                            detailFindCode, payUrlInfo.getApplicationFormCode(), payUrlInfo.getApplyPolicyNo(), payUrlInfo.getCpcNoticeNo());

                    PayUrlInfoEntity updEntity = new PayUrlInfoEntity();
                    updEntity.setIssueStatus("0");
                    updEntity.setIssueTimes(payUrlInfo.getIssueTimes() + 1);
                    updEntity.setId(payUrlInfo.getId());
                    payUrlInfoMapper.updateByPrimaryKeySelective(updEntity);

                    Document doc = DocumentHelper.createDocument();
                    Element info = doc.addElement("POLICYINFO");
                    doc.setRootElement(info);
                    info.addElement("SerialNo").addText(seqNo);  //序列号
                    info.addElement("policyNo").addText(payUrlInfo.getApplyPolicyNo()); //承保保单号
                    info.addElement("applicationNo").addText(payUrlInfo.getApplicationFormCode());//投保单号

                    log.info("{}调用太保查询保单号接口任务 调用数据交换中心报文{}", detailFindCode, info.asXML());

                    try {
                        // 3.调用数据交换中心
                        ResponseEntity<String> responseEntity = dexClient.text("edu", "202008181448050", "1.0", seqNo, info.asXML());

                        String ebody = responseEntity.getBody();

                        Document document = DocumentHelper.parseText(ebody);
                        Element ebodyElement = document.getRootElement();
                        String code = ebodyElement.element("ResponseCode").getStringValue();
                        if ("SUCCESS".equals(code)) {
                            IssueEnum issueEnum = IssueEnum.getIssueEnumByProCode(payUrlInfo.getProCode());
                            // 更新出单状态=2，保单号，更新时间
                            String policyNo = ebodyElement.element("PolicyNo").getStringValue();
                            payUrlInfo.setPolicyNo(policyNo);
                            String ePolicyParam = "";
                            if (issueEnum.equals(IssueEnum.CODE_40)) {
                                ePolicyParam = createLinYiEPolicyParam(seqNo, policyNo);
                            }
                            //成功后保存支付 超时
                            paySuccess(detailFindCode, payUrlInfo, issueEnum, ePolicyParam, info.asXML(), ebodyElement.asXML());

                        } else {
                            String msg = ebodyElement.element("ErrorMessage").getStringValue();
                            PayUrlInfoEntity qo = new PayUrlInfoEntity();
                            qo.setId(payUrlInfo.getId());
                            qo.setPolicyNoMessage(msg);
                            qo.setIssueStatus("3");
                            qo.setUpdateTime(DateUtils.getCurrentTime());
                            payUrlInfoMapper.updateByPrimaryKeySelective(qo);
                        }
                        log.info("{}调用太保查询保单号接口任务 调用数据交换中心返回结果{}", detailFindCode, JsonUtil.object2Json(responseEntity));
                    } catch (Exception e1) {
                        e1.printStackTrace();
                        log.info("{}调用太保查询保单号接口任务 e1异常{}", detailFindCode, e1);
                    }
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info("{}调用太保查询保单号接口任务 e异常{}", findCode, e);
        }
    }

    /**
     * 临沂请求电子保单报文
     *
     * @param seqNo
     * @param policyNo
     * @return
     */
    private String createLinYiEPolicyParam(String seqNo, String policyNo) {
        Document docs = DocumentHelper.createDocument();
        Element request = docs.addElement("request");
        docs.setRootElement(request);

        Element head = request.addElement("head");
        Element bodyEpolicy = request.addElement("body").addElement("epolicyInfoReprint");

        head.addElement("transactionCode").addText("108005");
        head.addElement("messageId").addText(seqNo);
        head.addElement("transactionEffectiveDate").addText(DateUtils.toYmdHms(new Date()));
        bodyEpolicy.addElement("policyNo").addText(policyNo);
        return request.asXML();
    }

    /**
     * 支付成功后处理
     *
     * @param detailFindCode 子日志code
     * @param payUrlInfo     payUrlInfo信息（注意需要带上保单号）
     * @param issueEnum      产品ifCode对应关系枚举
     * @param ePolicyParam   电子保单请求报文
     * @param reqPacket      请求时的入参 非必填
     * @param resPacket      请求结果 非必填
     */
    public void paySuccess(String detailFindCode, PayUrlInfoEntity payUrlInfo, IssueEnum issueEnum, String ePolicyParam, String reqPacket, String resPacket) {

        //更新payUrl表
        PayUrlInfoEntity qo = new PayUrlInfoEntity();
        qo.setId(payUrlInfo.getId());
        qo.setIssueStatus("2");
        qo.setPolicyNo(payUrlInfo.getPolicyNo());
        qo.setPayStatus(true);
        qo.setUpdateTime(DateUtils.getCurrentTime());
        payUrlInfoMapper.updateByPrimaryKeySelective(qo);

        log.info("{}调用太保查询保单号接口任务 调用数据交换中心返回保单号{}", detailFindCode, payUrlInfo.getPolicyNo());

        //修改pay_out 表的支付状态
        payOutService.updatePayStatus(payUrlInfo.getApplicationFormCode(), PayOutStatusEnum.SUCCESS);

        String appCode = payUrlInfo.getApplicationFormCode();
        // 保存到t_issue_record表
        IssueRecordEntity issueRecordEntity = new IssueRecordEntity();
        issueRecordEntity.setApplicationFormCode(appCode);
        //之后再添加产品在这块修改保险公司
        if (issueEnum.equals(IssueEnum.CODE_40)) {
            issueRecordEntity.setCompanyCode("0001300052.00541");
        }
        issueRecordEntity.setProCode(payUrlInfo.getProCode());
        issueRecordEntity.setReqPacket(reqPacket);
        issueRecordEntity.setResPacket(resPacket);
        issueRecordEntity.setSendStatus("2");
        issueRecordEntity.setPolicyNo(payUrlInfo.getPolicyNo());
        issueRecordEntity.setStatus("2");
        issueRecordEntity.setCreateTime(DateUtils.getCurrentTime());
        issueRecordEntity.setUpdateTime(DateUtils.getCurrentTime());
        issueRecordEntity.setIfCode(issueEnum.getIfCode());

        issueRecordEntityMapper.insertSelective(issueRecordEntity);
        log.info("{} t_issue_record表插入记录完成", detailFindCode);

        IssuePolicyLogEntity issuePolicyLogEntity = new IssuePolicyLogEntity();
        String consumeStatus = "1";
        issuePolicyLogEntity.setApplicationFormCode(payUrlInfo.getApplicationFormCode());
        issuePolicyLogEntity.setPolicyNo(payUrlInfo.getPolicyNo());
        issuePolicyLogEntity.setType("1");//电子保单
        issuePolicyLogEntity.setStatus(consumeStatus);
        issuePolicyLogEntity.setCreateTime(DateUtils.getCurrentTime());
        issuePolicyLogEntity.setUpdateTime(DateUtils.getCurrentTime());
        issuePolicyLogEntity.setProCode(payUrlInfo.getProCode());

        issuePolicyLogEntity.setParam(ePolicyParam);
        issuePolicyLogEntity.setIfCode(issueEnum.getIfCode());

        issuePolicyLogEntity.setTimes(0);
        issuePolicyLogEntityMapper.insertSelective(issuePolicyLogEntity);
    }

}
